using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;

namespace eHouse
{
    class Drivers
    {
        private static Drivers instance;
        public static string ip = "0.0.0.0";

        private OutputPort mled_kitchen;
        private OutputPort mled_living;
        private OutputPort mled_bedroom;
        private OutputPort mled_bathroom;

        private InputPort mwindow_kitchen;
        private InputPort mwindow_living;
        private InputPort mwindow_bedroom;
        private InputPort mwindow_bathroom;

        private OutputPort mled_irrigation;

        private InputPort alarmTrigger;

        //Temperature
        private const ushort address = 79;
        private const int clockRateKHz = 100;
        I2CDevice device;
        private OutputPort mled_heating;
        private OutputPort mled_AC;

        private Drivers()
        {
            //Lights
            mled_kitchen = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW1, false);
            mled_living = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW2, false);
            mled_bedroom = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW3, false);
            mled_bathroom = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW4, false);

            //Windows
            mwindow_kitchen = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW5, false, Port.ResistorMode.PullUp);
            mwindow_living = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW6, false, Port.ResistorMode.PullUp);
            mwindow_bedroom = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW8, false, Port.ResistorMode.PullUp);
            mwindow_bathroom = new InputPort(DeviceSolutions.SPOT.Hardware.Meridian.Pins.GPIO13, false, Port.ResistorMode.PullUp);

            //Irrigation
            mled_irrigation = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW7, false);

            //Temperature
            I2CDevice.Configuration config = new I2CDevice.Configuration(address, clockRateKHz);
            device = new I2CDevice(config);
            mled_heating = new OutputPort(DeviceSolutions.SPOT.Hardware.Meridian.Pins.GPIO10, false);
            mled_AC = new OutputPort(DeviceSolutions.SPOT.Hardware.Meridian.Pins.GPIO11, false);

            alarmTrigger = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW9, false, Port.ResistorMode.PullUp);
            
        }

        public static void createInstance()
        {
            instance = new Drivers();
        }

        public static Drivers getInstance()
        {
            return instance;
        }

        public double getTemperature()
        {
            double absolute_value;
            try
            {
                byte[] inBuffer = new byte[2];
                //I2CDevice.I2CReadTransaction readTransaction = new I2CDevice.I2CReadTransaction();
                I2CDevice.I2CReadTransaction readTransaction = device.CreateReadTransaction(inBuffer);

                //execute both transactions
                I2CDevice.I2CTransaction[] transactions = new I2CDevice.I2CTransaction[] { readTransaction };

                Thread.Sleep(1000);

                int transferred = device.Execute(transactions, 100);

                absolute_value = (inBuffer[0] << 1) >> 1;
                if (inBuffer[0] >> 7 == 1)
                    absolute_value = -absolute_value;

                if (inBuffer[1] >> 7 == 1)
                    absolute_value += 0.5;
            }
            catch (Exception)
            {
                absolute_value = 20.0;
            }

            
            return absolute_value;
        }       
        
        public OutputPort led_kitchen
        {
            get { return mled_kitchen; }
            set { mled_kitchen = value; }
        }

        public OutputPort led_living
        {
            get { return mled_living; }
            set { mled_living = value; }
        }

        public OutputPort led_bedroom
        {
            get { return mled_bedroom; }
            set { mled_bedroom = value; }
        }

        public OutputPort led_bathroom
        {
            get { return mled_bathroom; }
            set { mled_bathroom = value; }
        }

        public InputPort window_kitchen
        {
            get { return mwindow_kitchen; }
            set { mwindow_kitchen = value; }
        }

        public InputPort window_living
        {
            get { return mwindow_living; }
            set { mwindow_living = value; }
        }

        public InputPort window_bedroom
        {
            get { return mwindow_bedroom; }
            set { mwindow_bedroom = value; }
        }

        public InputPort window_bathroom
        {
            get { return mwindow_bathroom; }
            set { mwindow_bathroom = value; }
        }

        public OutputPort led_irrigation
        {
            get { return mled_irrigation; }
            set { mled_irrigation = value; }
        }

        public OutputPort led_heating
        {
            get { return mled_heating; }
            set { mled_heating = value; }
        }

        public OutputPort led_AC
        {
            get { return mled_AC; }
            set { mled_AC = value; }
        }


        public InputPort AlarmTrigger
        {
            get { return alarmTrigger; }
            set { alarmTrigger = value; }
        }
    }
}
